/*
- 通过预定义宏，控制测试框架的结构、断言、输出
- gtest测试需要的预定义宏	： _GTEST_
- mstest测试需要的预定义宏  ： _MTEST_
*/
#pragma once
#define _CRT_NONSTDC_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#ifdef _GTEST_
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#define TEST_CLASS(x) namespace x
#define TEST_METHOD(x) TEST(x,x)
#define GTEST_COUT std::cerr << "[INFO]"
#define TEST_COUT(msg) GTEST_COUT << msg
#define TEST_COUT_D(x) GTEST_COUT << x
const char TEST_F[] = "gtest_";
#else
#ifdef _MTEST_
#include "CppUnitTest.h"
#define TEST(iclass,ifunction)  public: TEST_METHOD(ifunction)
#define EXPECT_NEAR(x,y,e)  Assert::AreEqual(x, y, e)
#define EXPECT_EQ(x,y)  Assert::AreEqual(x, y)
#define EXPECT_TRUE(x)  Assert::IsTrue(x)
#define EXPECT_FALSE(x)  Assert::IsFalse(x)
#define TEST_COUT(msg) Logger::WriteMessage(msg)
#define TEST_COUT_D(x) Logger::WriteMessage((std::to_string(x)).c_str())
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
const char TEST_F[] = "mtest_";
#else
const char TEST_F[] = "<NONE>";
#define TEST_COUT_D(x) printf("%d",x)
#define TEST_COUT(x) printf(x)
#endif // _MTEST_
#endif // _GTEST_


#include <stdlib.h>
#include <cstdlib>
#include <functional>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <map>

const static std::string H_TestFramework()
{
	return std::string(TEST_F);
}

const static std::string H_TimeString()
{
	time_t timep;
	time(&timep);
	char str[255];

#ifdef _MTEST_
	sprintf_s(str, "%d", (int)timep);
#else
	sprintf(str, "%d", (int)timep);
#endif //_MTEST_
	return std::string(str);
}

const static void H_print(int v)
{
	TEST_COUT_D(v);
}
const static void H_print(int v, bool value)
{
	TEST_COUT_D(v);
	if (value)
		TEST_COUT("\n");
}

const static void H_print(double v)
{
	TEST_COUT_D(v);
}
const static void H_print(double* v, int len)
{
	for (int i = 0; i < len; i++)
	{
		TEST_COUT_D(v[i]); TEST_COUT(",");
	}
}

const static void H_print(std::string v)
{
	TEST_COUT(v.c_str());
}

const static std::string H_ToString(std::vector<double> data)
{
	std::string s;
	for (size_t i = 0; i < data.size(); i++)
	{
		s = std::to_string(data[i]) + ",";
	}
	return s;
}

const static std::string H_ToString(double x, double y, double z)
{
	std::vector<double> arg = { x, y, z };
	return H_ToString(arg);
}

#include <ctype.h>
#include <cstdio>

static bool h_isspace(char ch)
{
	return
		ch == 0x20
		|| ch == 0x09
		|| ch == 0x0a
		|| ch == 0x0b
		|| ch == 0x0c
		|| ch == 0x0d
		;
}

//#define H_isspace(x) std::isspace(x)
#define H_isspace(x) h_isspace(x)
#define H_tolower(x) _tolower(x)
#define H_toupper(x) std::toupper(x)
#define H_atoi(x) std::atoi(x)
#define H_atof(x) std::atof(x)

//定义输出调试信息符号
#ifdef _H_TRACE
#define H_TRACE (printf("\nH_TRACE: %s(%d)--<%s>\n",__FILE__,__LINE__,__FUNCTION__),printf);
#define H_TRACE_FILE_LINE (printf("\nH_TRACE: %s(%d)  \n",__FILE__,__LINE__),printf);
#define H_TRACE_DATE_TIME (printf("\nH_TRACE: %s %s  \n",__DATE__,__TIME__),printf);
#else
#define H_TRACE //(printf("\nH_TRACE: %s(%d)--<%s>\n",__FILE__,__LINE__,__FUNCTION__),printf);
#define H_TRACE_FILE_LINE //(printf("\nH_TRACE: %s(%d)  \n",__FILE__,__LINE__),printf);
#define H_TRACE_DATE_TIME //(printf("\nH_TRACE: %s %s  \n",__DATE__,__TIME__),printf);
#endif // H_TRACE